package com.service.dialtest.service.impl;

import com.service.dialtest.controller.WebUserController;
import com.service.dialtest.dao.WebUserDao;
import com.service.dialtest.dto.LoginUserDto;
import com.service.dialtest.dto.WebUserDto;
import com.service.dialtest.dto.WebUserInfoDto;
import com.service.dialtest.entity.WebUserInfo;
import com.service.dialtest.service.UserInfoService;
import com.service.config.utils.*;
import com.service.dialtest.constant.Constant;
import com.service.dialtest.vo.WebUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.service.dialtest.constant.Constant.*;
import static com.service.dialtest.controller.WebUserController.clearCache;

@Slf4j
@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    private WebUserDao webUserDao;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    RestTemplate restTemplate;
    @Autowired
    private UserInfoService userInfoService;

    /**
     * 用户登录获取token
     * @param loginUserDto
     * @param httpServletRequest
     * @return
     * @throws Exception
     */
    @Override
    public HashMap getToken(LoginUserDto loginUserDto, HttpServletRequest httpServletRequest) throws Exception {
        HashMap map = new HashMap();
        String pwd = String.format(Locale.ROOT, "%s%s%s", com.service.config.constant.Constant.CIPHER_PREFIX, com.service.config.constant.Constant.COLON, DesUtil.encrypt(loginUserDto.getPassword()));
        loginUserDto.setPassword(pwd);
        WebUserInfo userInfo = userInfoService.queryAll(loginUserDto);
        if (userInfo == null) {
            return null;
        }
        if (userInfo.getStatus().equals("2") || userInfo.getStatus().equals("3")) {
            map.put("errorCode","您的账号已被封号，详情请查看您的邮箱");
            return map;
        }
        return getHashMap(loginUserDto, httpServletRequest, map, userInfo);
    }

    @Override
    public WebUserInfo queryAll(LoginUserDto loginUserDto) {
        return webUserDao.queryUserInfo(loginUserDto.getUsername(),loginUserDto.getPassword());
    }

    @Override
    public Result register(WebUserInfoDto userInfoDto, String realIp) throws Exception {
        WebUserInfo userInfo = ModelMapperUtil.strictMap(userInfoDto,WebUserInfo.class);
        WebUserInfo userInfo1 = webUserDao.queryUserByName(userInfo.getUsername());
        HashMap map = new HashMap(16);

        if (userInfo1 != null) {
            return Result.failure(Constant.USERNAME_REPEAT, Constant.USER_NAME_ALREADY_EXISTS_PLEASE_RE_ENTER);
        }

        userInfo.setId(IdUtil.getStringId());
        userInfo.setIp(realIp);
        userInfo.setAddTime(new Date());
        userInfo.setDate(new Date());
        userInfo.setCount(1);
        userInfo.setStatus("0");
        webUserDao.insert(userInfo);

        String token = UserTokenManager.generateToken(userInfo.getId());
        map.put("Token",token);
        redisUtil.setValue(token+userInfo.getId(), JsonXMLUtils.obj2json(userInfo)); // 存入缓存
        return Result.ok().setData(map);
    }

    @Override
    public Result queryByUserId(String userId) {
        WebUserInfo webUserInfo = webUserDao.queryById(userId);
        if(null!=webUserInfo)
        {
            WebUserVo webUserVo = ModelMapperUtil.strictMap(webUserInfo, WebUserVo.class);
            return Result.ok().setData(webUserVo);
        }
        return Result.failure(USER_NOT_FOUND,USER_DOES_NOT_EXIST);
    }

    @Override
    public Result updateUserInfo(WebUserInfoDto userInfoDto) throws Exception {
        WebUserInfo info = webUserDao.queryById(userInfoDto.getId());
        if(null == info)
        {
            return Result.failure(USER_NOT_FOUND,USER_DOES_NOT_EXIST);
        }

        //修改密码
        if(null!=userInfoDto.getNewPassword() && !"".equals(userInfoDto.getNewPassword()))
        {
            WebUserInfo userInfo = webUserDao.queryUserInfo(userInfoDto.getUsername(), userInfoDto.getPassword());
            if(null != userInfo)
            {
                if(userInfoDto.getPassword().equals(userInfoDto.getNewPassword()))
                {
                    return Result.failure(DATA_FORMAT_WRONG,"新旧密码不能一致");
                }
                webUserDao.updatePassword(userInfoDto);
                Set<String> strings = redisUtil.redisLike(userInfoDto.getId());
                clearCache(strings, redisUtil);
                return Result.ok();
            }
            return Result.failure(PWD_IS_WRONG,ORIGINAL_PASSWORD_INPUT_ERROR);
        }

        //修改用户信息(手机号、邮箱号、fullname、店铺名称、店铺性质)
        if((null != userInfoDto.getEMail() && !"".equals(userInfoDto.getEMail()))
                || (null!=userInfoDto.getTelephone())&& !"".equals(userInfoDto.getTelephone())
                || (null!=userInfoDto.getFullName())&& !"".equals(userInfoDto.getFullName())
                || (null!=userInfoDto.getShopName())&& !"".equals(userInfoDto.getShopName())
                || (null!=userInfoDto.getShopNameEn())&& !"".equals(userInfoDto.getShopNameEn())
                || (null!=userInfoDto.getShopNature())&& !"".equals(userInfoDto.getShopNature())
                || (null!=userInfoDto.getShopNatureEn())&& !"".equals(userInfoDto.getShopNatureEn())){
            if(null != userInfoDto)
            {
                WebUserInfo userInfo1 = ModelMapperUtil.strictMap(userInfoDto, WebUserInfo.class);
                if(userInfo1.getTelephone()!=null && userInfo1.getTelephone().length()!=11)
                {
                    return Result.failure(DATA_FORMAT_WRONG,"手机号格式有误");
                }
                if(userInfo1.getEMail()!=null)
                {
                    String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
                    Pattern p = Pattern.compile(regEx1);
                    Matcher m = p.matcher(userInfo1.getEMail());
                    if(!m.matches()){
                        return Result.failure(DATA_FORMAT_WRONG,"邮箱格式有误");
                    }
                }

                webUserDao.update(userInfo1);
                String token=UserTokenManager.generateToken(userInfo1.getId());
                Set<String> strings = redisUtil.redisLike(userInfo1.getId());
                clearCache(strings, redisUtil);
                WebUserDto userDto = ModelMapperUtil.strictMap(userInfo1, WebUserDto.class);
                userDto.setDate(new Date()); //登录时间
                redisUtil.setValue(token+userInfo1.getId(), JsonXMLUtils.obj2json(userDto)); // 存入缓存
                return Result.ok().setData(token);
            }
            return Result.failure(DATA_IS_WRONG,DATA_ERROR);
        }



        WebUserInfo webUserInfo = ModelMapperUtil.strictMap(userInfoDto, WebUserInfo.class);

        webUserDao.update(webUserInfo);
        return Result.ok();
    }

    /**
     * 修改数据
     *
     * @param userInfo 实例对象
     * @return 实例对象
     */
    @Override
    public WebUserInfo update(WebUserInfo userInfo) {
        webUserDao.update(userInfo);
        return this.queryById(userInfo.getId());
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public WebUserInfo queryById(String id) {
        return webUserDao.queryById(id);
    }
    /**
     * 根据强制登录标识符获取token
     * 强制标识符不存在且没有用户登录则直接返回token
     * 用户已登陆则直接返回用户重复登录码
     * @param loginUserDto
     * @param httpServletRequest
     * @param map
     * @param userInfo
     * @return
     * @throws Exception
     */
    private HashMap getHashMap(LoginUserDto loginUserDto, HttpServletRequest httpServletRequest, HashMap map, WebUserInfo userInfo) throws Exception {
        String realIp = getRealIp(httpServletRequest);
        WebUserDto userDto = ModelMapperUtil.strictMap(userInfo, WebUserDto.class);
        userDto.setIp(realIp); // 来源ip
        userDto.setDate(new Date()); //登录时间
        String token = "";
        Boolean isLogin = loginUserDto.getIsLogin();
        Set<String> strings = redisUtil.redisLike(userInfo.getId());
        if (isLogin != null) {
            if (isLogin) { // 强制登录标识符
                token = UserTokenManager.generateToken(userInfo.getId());
                clearCache(strings, redisUtil);
                HashMap map1 = setUserInfo(map, userInfo, userDto, token);
                return map1;
            }
        }
        if (strings.size() >= 1) {
            map.put("errorCode","用户重复登陆");
            return map ;
        }else {
            token = UserTokenManager.generateToken(userInfo.getId());
            HashMap map1 = setUserInfo(map, userInfo, userDto, token); //更新用户信息
            return map1;
        }
    }

    /**
     * 更新用户信息并返回token
     * @param map
     * @param userInfo
     * @param userDto
     * @param token
     * @return
     * @throws Exception
     */
    private HashMap setUserInfo(HashMap map, WebUserInfo userInfo, WebUserDto userDto, String token) throws Exception {
        userInfo.setCount(userInfo.getCount()+1);
        userInfo.setDate(userDto.getDate());
        userInfo.setIp(userDto.getIp());
        userInfoService.update(userInfo);
        redisUtil.setValue(token+userInfo.getId(), JsonXMLUtils.obj2json(userDto)); // 存入缓存
        map.put("Token",token);
        return map;
    }

    public String getRealIp(HttpServletRequest request) {
        return getString(request);

    }
    public static String getString(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        ip = getString(request, ip);
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static String getString(HttpServletRequest request, String ip) {
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        return ip;
    }
}
